package org.yar.activities;

import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import org.yar.R;
import org.yar.common.Preferences;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class FileBrowserActivity extends Activity {
	
	/*
	 * ViewHolder class for holding onto list item view references
	 */
	static class ViewHolder {
		ImageView ivIcon;
		TextView tvFilename;
		TextView tvDesc;
		
		File file;
	}
	
	static class FileComparator implements Comparator<File>
	{
		@Override
		public int compare(File f1, File f2)
		{
			if (f1.isDirectory() && !f2.isDirectory())
			{
				return -1;
			}
			else if (!f1.isDirectory() && f2.isDirectory())
			{
				return 1;
				
			}
			else
			{
				String f1Name = f1.getName();
				String f2Name = f2.getName();
				return f1Name.compareToIgnoreCase(f2Name);
			}
		}
	}
	
	/**
	 * Counts the number of files in the directory given by f.
	 * @param f the given directory
	 * @return
	 */
	static int countFiles(File f)
	{
		if (!f.isDirectory()) return -1;
		File [] files = f.listFiles();
		if (files == null) return -2;
		return files.length;
	}
	
	static String formatDesc(File f)

	{
		if (f.getName().equals(".."))
		{
			return "To parent directory";
		}
		
		if (f.isDirectory())
		{
			int fNum = countFiles(f);
			if (fNum < 0)
			{
				return "Unreadable";
			}
			else
			{
				return String.format("%d item%s", fNum, fNum != 1 ? "s" : "");
			}
		}
		else
		{
			return formatByteSize(f.length());
		}
	}
	
	static String formatByteSize(long sz)
	{
		DecimalFormat df = new DecimalFormat("#,###.#");
		if (sz > 10000000) return String.format("%s M", df.format(sz/1000000.0));
		if (sz > 10000) return String.format("%s K", df.format(sz/1000.0));
		return String.format("%s B", df.format(sz));
	}
	
	
	static class FileAdapter extends ArrayAdapter<File>{
		private LayoutInflater inflater;
		
		private int colorWhite;
		private int colorGray;
		
		private Bitmap iconFolder;
		private Bitmap iconFolderUnreadable;
		private Bitmap iconTextGeneric;
		
		public FileAdapter(Context context, int textViewResourceId, List<File> files) {
			super(context, textViewResourceId, files);
			
			inflater = LayoutInflater.from(context);
			
			iconFolder = BitmapFactory.decodeResource(context.getResources(), R.drawable.folder);
			iconFolderUnreadable = BitmapFactory.decodeResource(context.getResources(), R.drawable.folder_unreadable);
			iconTextGeneric = BitmapFactory.decodeResource(context.getResources(), R.drawable.text_x_generic);
			
			context.getResources().getColor(R.color.black);
			colorWhite = context.getResources().getColor(R.color.white);
			colorGray = context.getResources().getColor(R.color.gray);
		}
		
		
		private Bitmap getBitmap(File f)
		{
			if (f.isDirectory())
			{
				if (!f.canRead())
				{
					return iconFolderUnreadable;
				}
				
				return iconFolder;
			}
			else
			{
				return iconTextGeneric;
			}
		}
		
		private int getColor(File f)
		{
			
			if (f.isFile() && !f.canRead() || f.isDirectory() && !f.canWrite())
			{
				return colorGray;
			}
			else
			{
				return colorWhite;
			}
		}
		
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			
			if (convertView == null)
			{
				convertView = inflater.inflate(R.layout.file_item, null);
				
				holder = new ViewHolder();
				holder.ivIcon = (ImageView)convertView.findViewById(R.id.ivIcon);
				holder.tvFilename = (TextView)convertView.findViewById(R.id.tvFilename);
				holder.tvDesc = (TextView)convertView.findViewById(R.id.tvDesc);
				
				convertView.setTag(holder);
			}
			else
			{
				holder = (ViewHolder)convertView.getTag();
			}
			
			File f = getItem(position);
			
			holder.file = f;
			
			holder.tvFilename.setText(f.getName());
			holder.tvFilename.setTextColor(getColor(f));
			
			holder.tvDesc.setText(formatDesc(f));
			
			holder.ivIcon.setImageBitmap(getBitmap(f));
			
			return convertView;
		}
		
	}
	
	static final String TAG = "YetAnotherReader.FileBrowser";
	
	static final String FBROWSER_KEY_PATH = "PATH";
	
	private File currDir;
	private FileComparator fileComp;
	private FileAdapter fileAdapter;
	
	private ListView lvFiles;
	private TextView tvEmpty;
	
	private Preferences preferences;
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.file_browser);
        
        fileComp = new FileComparator();
        
        fileAdapter = new FileAdapter(this, R.layout.file_item, new ArrayList<File>());
        
        lvFiles = (ListView)findViewById(R.id.lvFiles);
        lvFiles.setLongClickable(true);
        lvFiles.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int position,
					long arg3) {
				
				File f = fileAdapter.getItem(position);
				
				if (!f.canRead())
				{
					return;
				}
				
				if (f.isFile())
				{
					openFile(f);
				}
				else if (f.isDirectory())
				{
					if (f.getName().endsWith(".."))
					{
						currDir = currDir.getParentFile();
						setCurrentDir(currDir);
					}
					else
					{
						currDir = f;
						setCurrentDir(currDir);
					}
					
						
				
					
				}
			}
		});
        tvEmpty = (TextView)findViewById(R.id.tvEmpty);
        lvFiles.setEmptyView(tvEmpty);

        registerForContextMenu(lvFiles);
        
        
    }
	
	@Override
	public void onResume()
	{
		super.onResume();
		
		preferences = new Preferences(this);
		
		/* TODO load user preferences here */
		String currPath = preferences.getRootString(FBROWSER_KEY_PATH, "/");
		
		currDir = new File(currPath);
		
		setCurrentDir(currDir);
	}
	
	@Override
	public void onPause()
	{
		super.onPause();
		
		
		/* TODO persist user preferences here */
		try {
			preferences.putRootString(FBROWSER_KEY_PATH, currDir.getCanonicalPath());
		} catch (Exception e)
		{
			Log.e(TAG, e.getMessage());
		}
		
		preferences.save();
		
	}
	
//	@Override
//	public void onBackPressed()
//	{
//		if (currDir.getParent() == null)
//		{
//			finish();
//			return;
//		}
//		
//		currDir = currDir.getParentFile();
//		setCurrentDir(currDir);
//	}
	
	/**
	 * Tries to open the file selected by the user. Determines if the file:
	 * 1) is a text file
	 * 2) has the read permissions
	 * 
	 * @param f
	 * @throws IOException 
	 */
	private void openFile(File f)
	{
		if (!f.canRead())
		{
			return;
		}
		
		String fname = f.getName();
		if (!fname.toLowerCase().endsWith(".txt"))
		{
			return;
		}
		
		try {
		Intent intent = new Intent();
		intent.setClass(FileBrowserActivity.this, ReaderActivity.class);
		intent.putExtra(ReaderActivity.READER_KEY_FILENAME, f.getCanonicalPath());
		
		startActivityForResult(intent, ReaderActivity.READER_CMD_OPEN_FILE);
		} catch (IOException ie)
		{
			Log.v(TAG, ie.getMessage());
		}
		
	}
	
	private void setCurrentDir(File dir)
	{
		Log.v(TAG, "Setting current directory to " + dir.getAbsolutePath() + " " + dir.getName());
		if (!dir.isDirectory())
		{
			return;
		}
		fileAdapter.clear();
		
		File [] files = dir.listFiles();
		
		Arrays.sort(files, fileComp);
		
		// the 'up a directory' file
		if (!dir.getName().equals(""))
		{
			fileAdapter.add(new File(".."));
		}
		for (File f: files)
		{
			fileAdapter.add(f);
		}
		lvFiles.setAdapter(fileAdapter);
		
		try {
			setTitle(dir.getCanonicalPath() + " (" + formatDesc(dir) + ")");
		} catch (IOException e)
		{
			Log.v(TAG, "Whoops");
			setTitle(dir.getAbsolutePath() + " (" + formatDesc(dir) + ")");
		}
	}
	
}
